package com.nativetalk.service.three.reserve.time.search;

import com.nativetalk.base.RetInfo;
import com.nativetalk.bean.TdNtReserveTime;
import com.nativetalk.bean.reserve.ScheduleList;
import com.nativetalk.bean.reserve.TdNtReserveTimeList;
import com.nativetalk.common.ValidationMessages;
import com.nativetalk.common.util.CommonUtil;
import com.nativetalk.common.util.GetTeacherUtil;
import com.nativetalk.dao.TdNtLiveCourseHisDao;
import com.nativetalk.dao.TdNtMembCourseSizeDao;
import com.nativetalk.dao.TdNtReserveDao;
import com.nativetalk.dao.TdNtReserveTimeDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by lizhun on 16/6/15.
 * Modified by wangzheng on 17/02/15
 */
@Service
public class ThreeReserveTimeSearchServiceImpl implements ThreeReserveTimeSearchService {
    /**
     * 老师可以安排时间的天数（老师可以安排14天以内的日程）
     */
    public static final int reserve_limit_days = 14;
    private static Logger logger = Logger.getLogger(ThreeReserveTimeSearchServiceImpl.class);
    @Resource
    private TdNtReserveTimeDao tdNtReserveTimeDao;
    @Resource
    private TdNtLiveCourseHisDao tdNtLiveCourseHisDao;
    @Resource
    private TdNtReserveDao tdNtReserveDao;
    @Resource
    private TdNtMembCourseSizeDao tdNtMembCourseSizeDao;
    private List<TdNtReserveTime> tdNtReserveDateLists;


    @Override
    public RetInfo findTeacherSetReserveTime(int tea_id, int week) {
        String logInfo = this.getClass().getName() + ":findTeacherSetReserveTime:";
        // 类路径+方法名
        logger.info("======" + logInfo + "begin======");
        RetInfo retInfo = new RetInfo();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("tea_id", tea_id);
            params.put("week", week);
            List<TdNtReserveTimeList> tdNtReserveTimeLists = tdNtReserveTimeDao.findTdNtReserveTimeList(params);
            retInfo.setMark(ValidationMessages.getValue("MARKYES"));
            retInfo.setTip("获取数据成功");
            Map<String, Object> map = new HashMap<>();
            map.put("reservetime", tdNtReserveTimeLists);
            retInfo.setObj(map);
        } catch (Exception e) {
            retInfo.setMark(ValidationMessages.getValue("MARKERROR"));
            retInfo.setTip(ValidationMessages.getValue("TIPERROR"));
            logger.error(e.getMessage(), e);
        }
        logger.info("======" + logInfo + "end======");
        return retInfo;
    }

    /**
     * @param tea_id    老师id
     * @param startDate 当前日期（yyyy-MM-dd）用户当地时区的时间戳，转换成date的对象，其小时部分就是用户当地时间与服务器相差的小时
     * @return
     * @Purpose 根据当前日期（date参数）查询用户预约时间计划列表（数据库表：td_nt_reserve_time）
     * @scence 4.1
     */
    @Override
    public RetInfo findAllTeacherReserveTime(int tea_id, Date startDate, TimeZone clientTimeZone) {
        logger.info("findTeacherReserveTime begin");
        RetInfo retInfo = new RetInfo();
        try {
            Date date1 = new Date(System.currentTimeMillis());
            long n1 = CommonUtil.distanceDays(date1,startDate);
            if (n1 > 6){
                startDate = new Date(date1.getTime() + 1000 * 60 * 60 * 24 * 7);
            }else if(n1 <= 6){
                startDate = date1;
            }
            // 2. 查询数据
            Map<String, Object> params = new HashMap<>();
            params.put("tea_id", tea_id);
            params.put("startDate", startDate);
            List<TdNtReserveTimeList> tdNtReserveTimeLists = tdNtReserveTimeDao.findTdNtReserveTime(params);
            Map<Date,Integer> stringIntegerMap = new HashMap<>();
            for(TdNtReserveTimeList tdNtReserveTimeList : tdNtReserveTimeLists){
                stringIntegerMap.put(tdNtReserveTimeList.getDate(),tdNtReserveTimeList.getIs_valid());
            }

            List<ScheduleList> scheduleLists = new ArrayList<>();
            Map<String, Object> map = new HashMap<>();
            for(int i = 0; i < 7; i++){
                ScheduleList scheduleList = new ScheduleList();
                Date date = new Date(startDate.getTime() + 1000 * 60 * 60 * 24 * i );
                params.put("startDate", date);
                List<TdNtReserveTimeList> tdNtReserveTimes = GetTeacherUtil.getReserveTime(date,clientTimeZone);
                for(TdNtReserveTimeList tdNtReserveTimeList1 : tdNtReserveTimes){
                    if(stringIntegerMap.get(tdNtReserveTimeList1.getDate()) != null){
                        tdNtReserveTimeList1.setIs_valid(stringIntegerMap.get(tdNtReserveTimeList1.getDate()));
                    }
                }
                scheduleList.setSchedule_date(date);
                scheduleList.setSchedule_list(tdNtReserveTimes);
                scheduleLists.add(scheduleList);
            }
            map.put("reservetime", scheduleLists);
            retInfo.setMark(ValidationMessages.getValue("MARKYES"));
            retInfo.setTip("数据查询成功");
            retInfo.setObj(map);
        } catch (Exception e) {
            retInfo.setMark(ValidationMessages.getValue("MARKERROR"));
            retInfo.setTip(ValidationMessages.getValue("TIPERROR"));
            logger.error(e.getMessage(), e);
        }
        logger.info("findTeacherReserveTime end.");
        return retInfo;
    }

    /**
     * @param startDate 当前日期
     * @param tea_id
     * @Purpose 验证是否有14天的数据（从当前日期开始直到第14天），如果数据不够14天需要补充数据
     * @version 4.1
     * @author Peter
     */
    @Transactional
    private void validateAndRepaireDate(int tea_id, Date startDate, Date endDate) {
        logger.info("==== validateAndRepaireDate start =====");
        List<Date> list = getDateList(tea_id, startDate, endDate);//实际有的数据
        logger.info("实际有的数据天数:" + list.size());
        //少于可以制定预约计划的天数（14天）需要补充数据
        if (list.size() < reserve_limit_days) {
            List<Date> shouldDataList = calculatorShouldHaveDays(startDate);//应该有的数据（14天）
            List<Date> missingDataList = new ArrayList<>();//缺少的数据
            for (Date sd : shouldDataList) {
                String sdStr = CommonUtil.formatYMD(sd);
                boolean isMissDay = true;
                for (Date rd : list) {
                    if (sdStr.equals(CommonUtil.formatYMD(rd))) {
                        isMissDay = false;
                    }
                }
                if (isMissDay) {
                    missingDataList.add(sd);
                }
            }
            logger.info("缺失的数据:" + missingDataList.size());
            logger.info("缺失的数据:" + missingDataList);
            repaireReserveDate(tea_id, missingDataList);
        }
        logger.info("==== validateAndRepaireDate end =====");
    }

    private List<Date> calculatorShouldHaveDays(Date startDate) {
        List<Date> shouldDataList = new ArrayList<>();//应该有的数据（14天）
        for (int i = 0; i < reserve_limit_days; i++) {
            Date shouldDate = CommonUtil.addData(startDate, i);
            shouldDataList.add(shouldDate);
        }
        return shouldDataList;
    }

    /**
     * @param startDate
     * @param tea_id
     * @return
     * @Purpose 查询老师预约时间表日期列表，仅有日期数据
     * @version 4.1
     * @author Peter
     */
    private List<Date> getDateList(int tea_id, Date startDate, Date endDate) {
        Map<String, Object> params = new HashMap<>();
        params.put("tea_id", tea_id);
        params.put("startDate", startDate);
        params.put("endDate", endDate);
        List<TdNtReserveTime> tdNtReserveDateLists = tdNtReserveTimeDao.findTdNtReserveDateList(params);
        List<Date> dateList = new ArrayList<>();
        for (TdNtReserveTime rt : tdNtReserveDateLists) {
            dateList.add(rt.getDate());
        }
        return dateList;
    }

    /**
     * 修补缺少的预约计划日期数据
     *
     * @param tea_id
     * @param missingDataList
     */
    @Transactional
    private void repaireReserveDate(int tea_id, List<Date> missingDataList) {
        List<TdNtReserveTime> reparedReserveTimeList = new ArrayList<>();
        for (Date missData : missingDataList) {
            for (int i = 0; i < 24; i++) {
                TdNtReserveTime rt = new TdNtReserveTime();

                rt.setDate(procHour(missData, i));
                rt.setIs_valid(1);
                rt.setReserve_time(i);
                rt.setTea_id(tea_id);
                rt.setReserve_week(CommonUtil.getWeekday(missData));
                reparedReserveTimeList.add(rt);
            }
        }
        long n = tdNtReserveTimeDao.repaireReserveDate(reparedReserveTimeList);
        System.out.println("插入数据：" + n);
    }

    //设置给定日期的小时为hour
    private Date procHour(Date date, int hour) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTime();
    }

    //将时间转换成客户端的时区
    private static void changeToClientTimeZone(TdNtReserveTimeList rt, TimeZone ctz) {

        //上海时区的时间
        Calendar lc = Calendar.getInstance();
        lc.setTime(rt.getDate());
//        lc.set(Calendar.HOUR_OF_DAY, 0);
//        rt.setDate(lc.getTime());//将date的小时去掉
        print(rt, lc);

        //客户端时区的时间
        Calendar cc = Calendar.getInstance();
        cc.setTime(rt.getDate());
        cc.setTimeZone(ctz);
//        rt.setReserve_time(cc.get(Calendar.HOUR_OF_DAY));//从日历中获取客户端的小时，然后设置到Reserve_time
        print(rt, cc);
    }

    private static void print(TdNtReserveTimeList rt, Calendar lc) {
        int year = lc.get(Calendar.YEAR);
        int month = lc.get(Calendar.MONTH) + 1;
        int day = lc.get(Calendar.DAY_OF_MONTH);
        int h = lc.get(Calendar.HOUR_OF_DAY);
        int m = lc.get(Calendar.MINUTE);
        int s = lc.get(Calendar.SECOND);
        String str = "";
        if ("Asia/Shanghai".equals(lc.getTimeZone().getID())) {
            str = "[" + lc.getTimeZone().getID() + "     " + year + "-" + month + "-" + day + " " + h + ":" + m + ":" + s + "] [" + rt.getIs_valid() + ", "  + ", " + rt.getDate().getTime() + "] ";
        } else {
            str = "[" + lc.getTimeZone().getID() + "  " + year + "-" + month + "-" + day + " " + h + ":" + m + ":" + s + "] [" + rt.getIs_valid() + ", "  + ", " + rt.getDate().getTime() + "] ";
        }
        logger.info(str);

    }

    public static void main(String[] args) {

        //{"reserve_time":18,"is_valid":1,"reserve_week":2,"date":1494324000000}
        TdNtReserveTimeList rt = new TdNtReserveTimeList();
        Date d = new Date();
        d.setTime(1494324000000L);
        rt.setDate(d);
//        rt.setReserve_time(18);
        rt.setIs_valid(1);
        TimeZone tz = TimeZone.getTimeZone("America/New_York");
        changeToClientTimeZone(rt, tz);
    }

}
